home *** CD-ROM | disk | FTP | other *** search
/ Netscape Plug-Ins Developer's Kit / Netscape_Plug-Ins_Developers_Kit.iso / CGIPERL / MACPERL / MSRCE418.HQX / Perl Source ƒ / Perl / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-15  |  37.8 KB  |  1,889 lines

  1. /* $RCSfile: util.c,v $$Revision: 4.0.1.6 $$Date: 92/06/11 21:18:47 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of the Perl Artistic License,
  6.  *    as specified in the README file.
  7.  *
  8.  * $Log:    util.c,v $
  9.  * Revision 4.0.1.6  92/06/11  21:18:47  lwall
  10.  * patch34: boneheaded typo in my_bcopy()
  11.  * 
  12.  * Revision 4.0.1.5  92/06/08  16:08:37  lwall
  13.  * patch20: removed implicit int declarations on functions
  14.  * patch20: Perl now distinguishes overlapped copies from non-overlapped
  15.  * patch20: fixed confusion between a *var's real name and its effective name
  16.  * patch20: bcopy() and memcpy() now tested for overlap safety
  17.  * patch20: added Atari ST portability
  18.  * 
  19.  * Revision 4.0.1.4  91/11/11  16:48:54  lwall
  20.  * patch19: study was busted by 4.018
  21.  * patch19: added little-endian pack/unpack options
  22.  * 
  23.  * Revision 4.0.1.3  91/11/05  19:18:26  lwall
  24.  * patch11: safe malloc code now integrated into Perl's malloc when possible
  25.  * patch11: index("little", "longer string") could visit faraway places
  26.  * patch11: warn '-' x 10000 dumped core
  27.  * patch11: forked exec on non-existent program now issues a warning
  28.  * 
  29.  * Revision 4.0.1.2  91/06/07  12:10:42  lwall
  30.  * patch4: new copyright notice
  31.  * patch4: made some allowances for "semi-standard" C
  32.  * patch4: index() could blow up searching for null string
  33.  * patch4: taintchecks could improperly modify parent in vfork()
  34.  * patch4: exec would close files even if you cleared close-on-exec flag
  35.  * 
  36.  * Revision 4.0.1.1  91/04/12  09:19:25  lwall
  37.  * patch1: random cleanup in cpp namespace
  38.  * 
  39.  * Revision 4.0  91/03/20  01:56:39  lwall
  40.  * 4.0 baseline.
  41.  * 
  42.  */
  43. /*SUPPRESS 112*/
  44.  
  45. #include "EXTERN.h"
  46. #include "perl.h"
  47.  
  48. #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
  49. #include <signal.h>
  50. #endif
  51.  
  52. #ifdef I_VFORK
  53. #  include <vfork.h>
  54. #endif
  55.  
  56. #ifdef I_VARARGS
  57. #  include <varargs.h>
  58. #endif
  59.  
  60. #ifdef I_FCNTL
  61. #  include <fcntl.h>
  62. #endif
  63. #ifdef I_SYS_FILE
  64. #  include <sys/file.h>
  65. #endif
  66.  
  67. #define FLUSH
  68.  
  69. #ifndef safemalloc
  70.  
  71. static char nomem[] = "Out of memory!\n";
  72.  
  73. /* paranoid version of malloc */
  74.  
  75. #ifdef DEBUGGING
  76. static int an = 0;
  77. #endif
  78.  
  79. /* NOTE:  Do not call the next three routines directly.  Use the macros
  80.  * in handy.h, so that we can easily redefine everything to do tracking of
  81.  * allocated hunks back to the original New to track down any memory leaks.
  82.  */
  83.  
  84. #ifdef macintosh
  85. extern void * gSacrificialGoat;
  86. #endif
  87.  
  88. char *
  89. safemalloc(size)
  90. #ifdef MSDOS
  91. unsigned long size;
  92. #else
  93. MEM_SIZE size;
  94. #endif /* MSDOS */
  95. {
  96.     char *ptr;
  97. #ifndef STDMAC
  98.     char *malloc();
  99. #endif /* ! STDMAC */
  100.  
  101. #ifdef MSDOS
  102.     if (size > 0xffff) {
  103.         fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
  104.         exit(1);
  105.     }
  106. #endif /* MSDOS */
  107. #ifdef DEBUGGING
  108.     if ((long)size < 0)
  109.     fatal("panic: malloc");
  110. #endif
  111.     ptr = malloc(size?size:1);    /* malloc(0) is NASTY on our system */
  112. #ifdef DEBUGGING
  113. #  if !(defined(I286) || defined(atarist))
  114. #ifdef macintosh
  115.     if (debug & 128)
  116.     fprintf(perldbg,"0x%x: (%05d) malloc %ld bytes\n",ptr,an++,(long)size);
  117. #else
  118.     if (debug & 128)
  119.     fprintf(stderr,"0x%x: (%05d) malloc %ld bytes\n",ptr,an++,(long)size);
  120. #endif
  121. #  else
  122.     if (debug & 128)
  123.     fprintf(stderr,"0x%lx: (%05d) malloc %ld bytes\n",ptr,an++,(long)size);
  124. #  endif
  125. #endif
  126. #ifdef macintosh
  127.     if (ptr != Nullch && gSacrificialGoat)
  128. #else
  129.     if (ptr != Nullch)
  130. #endif
  131.     return ptr;
  132.     else if (nomemok)
  133.     return Nullch;
  134.     else {
  135.     fputs(nomem,stderr) FLUSH;
  136.     exit(1);
  137.     }
  138.     /*NOTREACHED*/
  139. #ifdef lint
  140.     return ptr;
  141. #endif
  142. }
  143.  
  144. /* paranoid version of realloc */
  145.  
  146. char *
  147. saferealloc(where,size)
  148. char *where;
  149. #ifndef MSDOS
  150. MEM_SIZE size;
  151. #else
  152. unsigned long size;
  153. #endif /* MSDOS */
  154. {
  155.     char *ptr;
  156. #ifndef STDMAC
  157.     char *realloc();
  158. #endif /* ! STDMAC */
  159.  
  160. #ifdef MSDOS
  161.     if (size > 0xffff) {
  162.         fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
  163.         exit(1);
  164.     }
  165. #endif /* MSDOS */
  166.     if (!where)
  167.     fatal("Null realloc");
  168. #ifdef DEBUGGING
  169.     if ((long)size < 0)
  170.     fatal("panic: realloc");
  171. #endif
  172.     ptr = realloc(where,size?size:1);    /* realloc(0) is NASTY on our system */
  173. #ifdef DEBUGGING
  174. #  if !(defined(I286) || defined(atarist))
  175. #ifdef macintosh
  176.     if (debug & 128) {
  177.     fprintf(perldbg,"0x%x: (%05d) rfree\n",where,an++);
  178.     fprintf(perldbg,"0x%x: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
  179.     }
  180. #else
  181.     if (debug & 128) {
  182.     fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
  183.     fprintf(stderr,"0x%x: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
  184.     }
  185. #endif
  186. #  else
  187.     if (debug & 128) {
  188.     fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
  189.     fprintf(stderr,"0x%lx: (%05d) realloc %ld bytes\n",ptr,an++,(long)size);
  190.     }
  191. #  endif
  192. #endif
  193. #ifdef macintosh
  194.     if (ptr != Nullch && gSacrificialGoat)
  195. #else
  196.     if (ptr != Nullch)
  197. #endif
  198.     return ptr;
  199.     else if (nomemok)
  200.     return Nullch;
  201.     else {
  202.     fputs(nomem,stderr) FLUSH;
  203.     exit(1);
  204.     }
  205.     /*NOTREACHED*/
  206. #ifdef lint
  207.     return ptr;
  208. #endif
  209. }
  210.  
  211. /* safe version of free */
  212.  
  213. void
  214. safefree(where)
  215. char *where;
  216. {
  217. #ifdef DEBUGGING
  218. #  if !(defined(I286) || defined(atarist))
  219.     if (debug & 128)
  220. #ifdef macintosh
  221.     fprintf(perldbg,"0x%x: (%05d) free\n",where,an++);
  222. #else
  223.     fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
  224. #endif
  225. #  else
  226.     if (debug & 128)
  227.     fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
  228. #  endif
  229. #endif
  230.     if (where) {
  231.     /*SUPPRESS 701*/
  232.     free(where);
  233.     }
  234. }
  235.  
  236. #endif /* !safemalloc */
  237.  
  238. #ifdef LEAKTEST
  239.  
  240. #define ALIGN sizeof(long)
  241.  
  242. char *
  243. safexmalloc(x,size)
  244. int x;
  245. MEM_SIZE size;
  246. {
  247.     register char *where;
  248.  
  249.     where = safemalloc(size + ALIGN);
  250.     xcount[x]++;
  251.     where[0] = x % 100;
  252.     where[1] = x / 100;
  253.     return where + ALIGN;
  254. }
  255.  
  256. char *
  257. safexrealloc(where,size)
  258. char *where;
  259. MEM_SIZE size;
  260. {
  261.     return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
  262. }
  263.  
  264. void
  265. safexfree(where)
  266. char *where;
  267. {
  268.     int x;
  269.  
  270.     if (!where)
  271.     return;
  272.     where -= ALIGN;
  273.     x = where[0] + 100 * where[1];
  274.     xcount[x]--;
  275.     safefree(where);
  276. }
  277.  
  278. static void
  279. xstat()
  280. {
  281.     register int i;
  282.  
  283.     for (i = 0; i < MAXXCOUNT; i++) {
  284.     if (xcount[i] > lastxcount[i]) {
  285.         fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
  286.         lastxcount[i] = xcount[i];
  287.     }
  288.     }
  289. }
  290.  
  291. #endif /* LEAKTEST */
  292.  
  293. /* copy a string up to some (non-backslashed) delimiter, if any */
  294.  
  295. char *
  296. cpytill(to,from,fromend,delim,retlen)
  297. register char *to;
  298. register char *from;
  299. register char *fromend;
  300. register int delim;
  301. int *retlen;
  302. {
  303.     char *origto = to;
  304.  
  305.     for (; from < fromend; from++,to++) {
  306.     if (*from == '\\') {
  307.         if (from[1] == delim)
  308.         from++;
  309.         else if (from[1] == '\\')
  310.         *to++ = *from++;
  311.     }
  312.     else if (*from == delim)
  313.         break;
  314.     *to = *from;
  315.     }
  316.     *to = '\0';
  317.     *retlen = to - origto;
  318.     return from;
  319. }
  320.  
  321. /* return ptr to little string in big string, NULL if not found */
  322. /* This routine was donated by Corey Satten. */
  323.  
  324. char *
  325. instr(big, little)
  326. register char *big;
  327. register char *little;
  328. {
  329.     register char *s, *x;
  330.     register int first;
  331.  
  332.     if (!little)
  333.     return big;
  334.     first = *little++;
  335.     if (!first)
  336.     return big;
  337.     while (*big) {
  338.     if (*big++ != first)
  339.         continue;
  340.     for (x=big,s=little; *s; /**/ ) {
  341.         if (!*x)
  342.         return Nullch;
  343.         if (*s++ != *x++) {
  344.         s--;
  345.         break;
  346.         }
  347.     }
  348.     if (!*s)
  349.         return big-1;
  350.     }
  351.     return Nullch;
  352. }
  353.  
  354. /* same as instr but allow embedded nulls */
  355.  
  356. char *
  357. ninstr(big, bigend, little, lend)
  358. register char *big;
  359. register char *bigend;
  360. char *little;
  361. char *lend;
  362. {
  363.     register char *s, *x;
  364.     register int first = *little;
  365.     register char *littleend = lend;
  366.  
  367.     if (!first && little > littleend)
  368.     return big;
  369.     if (bigend - big < littleend - little)
  370.     return Nullch;
  371.     bigend -= littleend - little++;
  372.     while (big <= bigend) {
  373.     if (*big++ != first)
  374.         continue;
  375.     for (x=big,s=little; s < littleend; /**/ ) {
  376.         if (*s++ != *x++) {
  377.         s--;
  378.         break;
  379.         }
  380.     }
  381.     if (s >= littleend)
  382.         return big-1;
  383.     }
  384.     return Nullch;
  385. }
  386.  
  387. /* reverse of the above--find last substring */
  388.  
  389. char *
  390. rninstr(big, bigend, little, lend)
  391. register char *big;
  392. char *bigend;
  393. char *little;
  394. char *lend;
  395. {
  396.     register char *bigbeg;
  397.     register char *s, *x;
  398.     register int first = *little;
  399.     register char *littleend = lend;
  400.  
  401.     if (!first && little > littleend)
  402.     return bigend;
  403.     bigbeg = big;
  404.     big = bigend - (littleend - little++);
  405.     while (big >= bigbeg) {
  406.     if (*big-- != first)
  407.         continue;
  408.     for (x=big+2,s=little; s < littleend; /**/ ) {
  409.         if (*s++ != *x++) {
  410.         s--;
  411.         break;
  412.         }
  413.     }
  414.     if (s >= littleend)
  415.         return big+1;
  416.     }
  417.     return Nullch;
  418. }
  419.  
  420. unsigned char fold[] = {
  421.     0,    1,    2,    3,    4,    5,    6,    7,
  422.     8,    9,    10,    11,    12,    13,    14,    15,
  423.     16,    17,    18,    19,    20,    21,    22,    23,
  424.     24,    25,    26,    27,    28,    29,    30,    31,
  425.     32,    33,    34,    35,    36,    37,    38,    39,
  426.     40,    41,    42,    43,    44,    45,    46,    47,
  427.     48,    49,    50,    51,    52,    53,    54,    55,
  428.     56,    57,    58,    59,    60,    61,    62,    63,
  429.     64,    'a',    'b',    'c',    'd',    'e',    'f',    'g',
  430.     'h',    'i',    'j',    'k',    'l',    'm',    'n',    'o',
  431.     'p',    'q',    'r',    's',    't',    'u',    'v',    'w',
  432.     'x',    'y',    'z',    91,    92,    93,    94,    95,
  433.     96,    'A',    'B',    'C',    'D',    'E',    'F',    'G',
  434.     'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
  435.     'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
  436.     'X',    'Y',    'Z',    123,    124,    125,    126,    127,
  437.     128,    129,    130,    131,    132,    133,    134,    135,
  438.     136,    137,    138,    139,    140,    141,    142,    143,
  439.     144,    145,    146,    147,    148,    149,    150,    151,
  440.     152,    153,    154,    155,    156,    157,    158,    159,
  441.     160,    161,    162,    163,    164,    165,    166,    167,
  442.     168,    169,    170,    171,    172,    173,    174,    175,
  443.     176,    177,    178,    179,    180,    181,    182,    183,
  444.     184,    185,    186,    187,    188,    189,    190,    191,
  445.     192,    193,    194,    195,    196,    197,    198,    199,
  446.     200,    201,    202,    203,    204,    205,    206,    207,
  447.     208,    209,    210,    211,    212,    213,    214,    215,
  448.     216,    217,    218,    219,    220,    221,    222,    223,    
  449.     224,    225,    226,    227,    228,    229,    230,    231,
  450.     232,    233,    234,    235,    236,    237,    238,    239,
  451.     240,    241,    242,    243,    244,    245,    246,    247,
  452.     248,    249,    250,    251,    252,    253,    254,    255
  453. };
  454.  
  455. static unsigned char freq[] = {
  456.     1,    2,    84,    151,    154,    155,    156,    157,
  457.     165,    246,    250,    3,    158,    7,    18,    29,
  458.     40,    51,    62,    73,    85,    96,    107,    118,
  459.     129,    140,    147,    148,    149,    150,    152,    153,
  460.     255,    182,    224,    205,    174,    176,    180,    217,
  461.     233,    232,    236,    187,    235,    228,    234,    226,
  462.     222,    219,    211,    195,    188,    193,    185,    184,
  463.     191,    183,    201,    229,    181,    220,    194,    162,
  464.     163,    208,    186,    202,    200,    218,    198,    179,
  465.     178,    214,    166,    170,    207,    199,    209,    206,
  466.     204,    160,    212,    216,    215,    192,    175,    173,
  467.     243,    172,    161,    190,    203,    189,    164,    230,
  468.     167,    248,    227,    244,    242,    255,    241,    231,
  469.     240,    253,    169,    210,    245,    237,    249,    247,
  470.     239,    168,    252,    251,    254,    238,    223,    221,
  471.     213,    225,    177,    197,    171,    196,    159,    4,
  472.     5,    6,    8,    9,    10,    11,    12,    13,
  473.     14,    15,    16,    17,    19,    20,    21,    22,
  474.     23,    24,    25,    26,    27,    28,    30,    31,
  475.     32,    33,    34,    35,    36,    37,    38,    39,
  476.     41,    42,    43,    44,    45,    46,    47,    48,
  477.     49,    50,    52,    53,    54,    55,    56,    57,
  478.     58,    59,    60,    61,    63,    64,    65,    66,
  479.     67,    68,    69,    70,    71,    72,    74,    75,
  480.     76,    77,    78,    79,    80,    81,    82,    83,
  481.     86,    87,    88,    89,    90,    91,    92,    93,
  482.     94,    95,    97,    98,    99,    100,    101,    102,
  483.     103,    104,    105,    106,    108,    109,    110,    111,
  484.     112,    113,    114,    115,    116,    117,    119,    120,
  485.     121,    122,    123,    124,    125,    126,    127,    128,
  486.     130,    131,    132,    133,    134,    135,    136,    137,
  487.     138,    139,    141,    142,    143,    144,    145,    146
  488. };
  489.  
  490. void
  491. fbmcompile(str, iflag)
  492. STR *str;
  493. int iflag;
  494. {
  495.     register unsigned char *s;
  496.     register unsigned char *table;
  497.     register unsigned int i;
  498.     register unsigned int len = str->str_cur;
  499.     int rarest = 0;
  500.     unsigned int frequency = 256;
  501.  
  502.     Str_Grow(str,len+258);
  503. #ifndef lint
  504.     table = (unsigned char*)(str->str_ptr + len + 1);
  505. #else
  506.     table = Null(unsigned char*);
  507. #endif
  508.     s = table - 2;
  509.     for (i = 0; i < 256; i++) {
  510.     table[i] = len;
  511.     }
  512.     i = 0;
  513. #ifndef lint
  514.     while (s >= (unsigned char*)(str->str_ptr))
  515. #endif
  516.     {
  517.     if (table[*s] == len) {
  518. #ifndef pdp11
  519.         if (iflag)
  520.         table[*s] = table[fold[*s]] = i;
  521. #else
  522.         if (iflag) {
  523.         int j;
  524.         j = fold[*s];
  525.         table[j] = i;
  526.         table[*s] = i;
  527.         }
  528. #endif /* pdp11 */
  529.         else
  530.         table[*s] = i;
  531.     }
  532.     s--,i++;
  533.     }
  534.     str->str_pok |= SP_FBM;        /* deep magic */
  535.  
  536. #ifndef lint
  537.     s = (unsigned char*)(str->str_ptr);        /* deeper magic */
  538. #else
  539.     s = Null(unsigned char*);
  540. #endif
  541.     if (iflag) {
  542.     register unsigned int tmp, foldtmp;
  543.     str->str_pok |= SP_CASEFOLD;
  544.     for (i = 0; i < len; i++) {
  545.         tmp=freq[s[i]];
  546.         foldtmp=freq[fold[s[i]]];
  547.         if (tmp < frequency && foldtmp < frequency) {
  548.         rarest = i;
  549.         /* choose most frequent among the two */
  550.         frequency = (tmp > foldtmp) ? tmp : foldtmp;
  551.         }
  552.     }
  553.     }
  554.     else {
  555.     for (i = 0; i < len; i++) {
  556.         if (freq[s[i]] < frequency) {
  557.         rarest = i;
  558.         frequency = freq[s[i]];
  559.         }
  560.     }
  561.     }
  562.     str->str_rare = s[rarest];
  563.     str->str_state = rarest;
  564. #ifdef DEBUGGING
  565.     if (debug & 512)
  566. #ifdef macintosh
  567.     fprintf(perldbg,"rarest char %c at %d\n",str->str_rare, str->str_state);
  568. #else
  569.     fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
  570. #endif
  571. #endif
  572. }
  573.  
  574. char *
  575. fbminstr(big, bigend, littlestr)
  576. unsigned char *big;
  577. register unsigned char *bigend;
  578. STR *littlestr;
  579. {
  580.     register unsigned char *s;
  581.     register int tmp;
  582.     register int littlelen;
  583.     register unsigned char *little;
  584.     register unsigned char *table;
  585.     register unsigned char *olds;
  586.     register unsigned char *oldlittle;
  587.  
  588. #ifndef lint
  589.     if (!(littlestr->str_pok & SP_FBM)) {
  590.     if (!littlestr->str_ptr)
  591.         return (char*)big;
  592.     return ninstr((char*)big,(char*)bigend,
  593.         littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
  594.     }
  595. #endif
  596.  
  597.     littlelen = littlestr->str_cur;
  598. #ifndef lint
  599.     if (littlestr->str_pok & SP_TAIL && !multiline) {    /* tail anchored? */
  600.     if (littlelen > bigend - big)
  601.         return Nullch;
  602.     little = (unsigned char*)littlestr->str_ptr;
  603.     if (littlestr->str_pok & SP_CASEFOLD) {    /* oops, fake it */
  604.         big = bigend - littlelen;        /* just start near end */
  605.         if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
  606.         big--;
  607.     }
  608.     else {
  609.         s = bigend - littlelen;
  610.         if (*s == *little && bcmp(s,little,littlelen)==0)
  611.         return (char*)s;        /* how sweet it is */
  612.         else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
  613.           && s > big) {
  614.             s--;
  615.         if (*s == *little && bcmp(s,little,littlelen)==0)
  616.             return (char*)s;
  617.         }
  618.         return Nullch;
  619.     }
  620.     }
  621.     table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
  622. #else
  623.     table = Null(unsigned char*);
  624. #endif
  625.     if (--littlelen >= bigend - big)
  626.     return Nullch;
  627.     s = big + littlelen;
  628.     oldlittle = little = table - 2;
  629.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insensitive? */
  630.     if (s < bigend) {
  631.       top1:
  632.         /*SUPPRESS 560*/
  633.         if (tmp = table[*s]) {
  634. #ifdef POINTERRIGOR
  635.         if (bigend - s > tmp) {
  636.             s += tmp;
  637.             goto top1;
  638.         }
  639. #else
  640.         if ((s += tmp) < bigend)
  641.             goto top1;
  642. #endif
  643.         return Nullch;
  644.         }
  645.         else {
  646.         tmp = littlelen;    /* less expensive than calling strncmp() */
  647.         olds = s;
  648.         while (tmp--) {
  649.             if (*--s == *--little || fold[*s] == *little)
  650.             continue;
  651.             s = olds + 1;    /* here we pay the price for failure */
  652.             little = oldlittle;
  653.             if (s < bigend)    /* fake up continue to outer loop */
  654.             goto top1;
  655.             return Nullch;
  656.         }
  657. #ifndef lint
  658.         return (char *)s;
  659. #endif
  660.         }
  661.     }
  662.     }
  663.     else {
  664.     if (s < bigend) {
  665.       top2:
  666.         /*SUPPRESS 560*/
  667.         if (tmp = table[*s]) {
  668. #ifdef POINTERRIGOR
  669.         if (bigend - s > tmp) {
  670.             s += tmp;
  671.             goto top2;
  672.         }
  673. #else
  674.         if ((s += tmp) < bigend)
  675.             goto top2;
  676. #endif
  677.         return Nullch;
  678.         }
  679.         else {
  680.         tmp = littlelen;    /* less expensive than calling strncmp() */
  681.         olds = s;
  682.         while (tmp--) {
  683.             if (*--s == *--little)
  684.             continue;
  685.             s = olds + 1;    /* here we pay the price for failure */
  686.             little = oldlittle;
  687.             if (s < bigend)    /* fake up continue to outer loop */
  688.             goto top2;
  689.             return Nullch;
  690.         }
  691. #ifndef lint
  692.         return (char *)s;
  693. #endif
  694.         }
  695.     }
  696.     }
  697.     return Nullch;
  698. }
  699.  
  700. char *
  701. screaminstr(bigstr, littlestr)
  702. STR *bigstr;
  703. STR *littlestr;
  704. {
  705.     register unsigned char *s, *x;
  706.     register unsigned char *big;
  707.     register int pos;
  708.     register int previous;
  709.     register int first;
  710.     register unsigned char *little;
  711.     register unsigned char *bigend;
  712.     register unsigned char *littleend;
  713.  
  714.     if ((pos = screamfirst[littlestr->str_rare]) < 0) 
  715.     return Nullch;
  716. #ifndef lint
  717.     little = (unsigned char *)(littlestr->str_ptr);
  718. #else
  719.     little = Null(unsigned char *);
  720. #endif
  721.     littleend = little + littlestr->str_cur;
  722.     first = *little++;
  723.     previous = littlestr->str_state;
  724. #ifndef lint
  725.     big = (unsigned char *)(bigstr->str_ptr);
  726. #else
  727.     big = Null(unsigned char*);
  728. #endif
  729.     bigend = big + bigstr->str_cur;
  730.     while (pos < previous) {
  731. #ifndef lint
  732.     if (!(pos += screamnext[pos]))
  733. #endif
  734.         return Nullch;
  735.     }
  736. #ifdef POINTERRIGOR
  737.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insignificant? */
  738.     do {
  739.         if (big[pos-previous] != first && big[pos-previous] != fold[first])
  740.         continue;
  741.         for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
  742.         if (x >= bigend)
  743.             return Nullch;
  744.         if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
  745.             s--;
  746.             break;
  747.         }
  748.         }
  749.         if (s == littleend)
  750. #ifndef lint
  751.         return (char *)(big+pos-previous);
  752. #else
  753.         return Nullch;
  754. #endif
  755.     } while (
  756. #ifndef lint
  757.         pos += screamnext[pos]    /* does this goof up anywhere? */
  758. #else
  759.         pos += screamnext[0]
  760. #endif
  761.         );
  762.     }
  763.     else {
  764.     do {
  765.         if (big[pos-previous] != first)
  766.         continue;
  767.         for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
  768.         if (x >= bigend)
  769.             return Nullch;
  770.         if (*s++ != *x++) {
  771.             s--;
  772.             break;
  773.         }
  774.         }
  775.         if (s == littleend)
  776. #ifndef lint
  777.         return (char *)(big+pos-previous);
  778. #else
  779.         return Nullch;
  780. #endif
  781.     } while (
  782. #ifndef lint
  783.         pos += screamnext[pos]
  784. #else
  785.         pos += screamnext[0]
  786. #endif
  787.         );
  788.     }
  789. #else /* !POINTERRIGOR */
  790.     big -= previous;
  791.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insignificant? */
  792.     do {
  793.         if (big[pos] != first && big[pos] != fold[first])
  794.         continue;
  795.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  796.         if (x >= bigend)
  797.             return Nullch;
  798.         if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
  799.             s--;
  800.             break;
  801.         }
  802.         }
  803.         if (s == littleend)
  804. #ifndef lint
  805.         return (char *)(big+pos);
  806. #else
  807.         return Nullch;
  808. #endif
  809.     } while (
  810. #ifndef lint
  811.         pos += screamnext[pos]    /* does this goof up anywhere? */
  812. #else
  813.         pos += screamnext[0]
  814. #endif
  815.         );
  816.     }
  817.     else {
  818.     do {
  819.         if (big[pos] != first)
  820.         continue;
  821.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  822.         if (x >= bigend)
  823.             return Nullch;
  824.         if (*s++ != *x++) {
  825.             s--;
  826.             break;
  827.         }
  828.         }
  829.         if (s == littleend)
  830. #ifndef lint
  831.         return (char *)(big+pos);
  832. #else
  833.         return Nullch;
  834. #endif
  835.     } while (
  836. #ifndef lint
  837.         pos += screamnext[pos]
  838. #else
  839.         pos += screamnext[0]
  840. #endif
  841.         );
  842.     }
  843. #endif /* POINTERRIGOR */
  844.     return Nullch;
  845. }
  846.  
  847. /* copy a string to a safe spot */
  848.  
  849. char *
  850. savestr(str)
  851. char *str;
  852. {
  853.     register char *newaddr;
  854.  
  855.     New(902,newaddr,strlen(str)+1,char);
  856.     (void)strcpy(newaddr,str);
  857.     return newaddr;
  858. }
  859.  
  860. /* same thing but with a known length */
  861.  
  862. char *
  863. nsavestr(str, len)
  864. char *str;
  865. register int len;
  866. {
  867.     register char *newaddr;
  868.  
  869.     New(903,newaddr,len+1,char);
  870.     Copy(str,newaddr,len,char);        /* might not be null terminated */
  871.     newaddr[len] = '\0';        /* is now */
  872.     return newaddr;
  873. }
  874.  
  875. /* grow a static string to at least a certain length */
  876.  
  877. void
  878. growstr(strptr,curlen,newlen)
  879. char **strptr;
  880. int *curlen;
  881. int newlen;
  882. {
  883.     if (newlen > *curlen) {        /* need more room? */
  884.     if (*curlen)
  885.         Renew(*strptr,newlen,char);
  886.     else
  887.         New(905,*strptr,newlen,char);
  888.     *curlen = newlen;
  889.     }
  890. }
  891.  
  892. #ifdef macintosh
  893.  
  894. char * MPWFileName(char * file)
  895. {
  896.     if (!strcmp(file, "Dev:Pseudo"))
  897.         return gPseudoFileName;
  898.     else if (!strncmp(file, "Dev:Pseudo:", 11))
  899.         return file + 11;
  900.     else
  901.         return file;
  902. }
  903.  
  904. char * MPWPosIndication(char * buf, char * file, long line)
  905. {
  906.     file = MPWFileName(file);
  907.  
  908.     if (gFirstErrorLine == -1 && !Path2FSSpec(file, &gFirstErrorFile))
  909.         gFirstErrorLine = line;
  910.     
  911.     strcpy(buf, "File '"); 
  912.     buf += 6;
  913.     
  914.     while (*file) 
  915.         if (*file == '\'') {
  916.         strcpy(buf, "'╢''");
  917.         buf += 3;
  918.         ++file;
  919.     } else
  920.         *buf++ = *file++;
  921.         
  922.     if (buf[-1] == '\'' && buf[-2] == '\'')
  923.         --buf;
  924.     else
  925.         *buf++ = '\'';
  926.  
  927.     return buf + sprintf(buf, "; Line %ld", line);
  928. }
  929. #endif
  930.  
  931. #ifndef I_VARARGS
  932. /*VARARGS1*/
  933. char *
  934. mess(pat,a1,a2,a3,a4)
  935. char *pat;
  936. long a1, a2, a3, a4;
  937. {
  938.     char *s;
  939.     int usermess = strEQ(pat,"%s");
  940.     STR *tmpstr;
  941.  
  942.     s = buf;
  943. #ifdef macintosh
  944.     if (usermess) {
  945.     tmpstr = str_mortal(&str_undef);
  946.     str_set(tmpstr, "# ");
  947.     str_cat(tmpstr, (char*)a1);
  948.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  949.     }
  950.     else {
  951.         (void) sprintf(buf, "# ");
  952.         s += 2;
  953.     (void)sprintf(s,pat,a1,a2,a3,a4);
  954.     s += strlen(s);
  955.     }
  956. #else
  957.     if (usermess) {
  958.     tmpstr = str_mortal(&str_undef);
  959.     str_set(tmpstr, (char*)a1);
  960.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  961.     }
  962.     else {
  963.     (void)sprintf(s,pat,a1,a2,a3,a4);
  964.     s += strlen(s);
  965.     }
  966. #endif
  967.  
  968.     if (s[-1] != '\n') {
  969. #ifdef macintosh
  970.     if (last_in_stab &&
  971.         stab_io(last_in_stab) &&
  972.         stab_io(last_in_stab)->lines ) {
  973.         if (s[-1] != '.')
  974.             *s++ = '.';
  975.         (void)sprintf(s," Input from <%s>, line %ld",
  976.           last_in_stab == argvstab ? "" : stab_name(last_in_stab),
  977.           (long)stab_io(last_in_stab)->lines);
  978.         s += strlen(s);
  979.     }
  980.     if (curcmd->c_line) {
  981.         s[0] = '\n';
  982.         s = MPWPosIndication(
  983.                 s+1, 
  984.             stab_val(curcmd->c_filestab)->str_ptr, 
  985.             (long)curcmd->c_line);
  986.     }
  987.     (void)strcpy(s,"\n");
  988. #else
  989.     if (curcmd->c_line) {
  990.         (void)sprintf(s," at %s line %ld",
  991.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  992.         s += strlen(s);
  993.     }
  994.     if (last_in_stab &&
  995.         stab_io(last_in_stab) &&
  996.         stab_io(last_in_stab)->lines ) {
  997.         (void)sprintf(s,", <%s> line %ld",
  998.           last_in_stab == argvstab ? "" : stab_ename(last_in_stab),
  999.           (long)stab_io(last_in_stab)->lines);
  1000.         s += strlen(s);
  1001.     }
  1002.     (void)strcpy(s,".\n");
  1003. #endif
  1004.     if (usermess)
  1005.         str_cat(tmpstr,buf+1);
  1006.     }
  1007.     if (usermess)
  1008.     return tmpstr->str_ptr;
  1009.     else
  1010.     return buf;
  1011. }
  1012.  
  1013. /*VARARGS1*/
  1014. void fatal(pat,a1,a2,a3,a4)
  1015. char *pat;
  1016. long a1, a2, a3, a4;
  1017. {
  1018.     extern FILE *e_fp;
  1019.     extern char *e_tmpname;
  1020.     char *tmps;
  1021.     char *message;
  1022.  
  1023.     message = mess(pat,a1,a2,a3,a4);
  1024.     if (in_eval) {
  1025.     str_set(stab_val(stabent("@",TRUE)),message);
  1026.     tmps = "_EVAL_";
  1027.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  1028.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  1029. #ifdef DEBUGGING
  1030.         if (debug & 4) {
  1031.         deb("(Skipping label #%d %s)\n",loop_ptr,
  1032.             loop_stack[loop_ptr].loop_label);
  1033.         }
  1034. #endif
  1035.         loop_ptr--;
  1036.     }
  1037. #ifdef DEBUGGING
  1038.     if (debug & 4) {
  1039.         deb("(Found label #%d %s)\n",loop_ptr,
  1040.         loop_stack[loop_ptr].loop_label);
  1041.     }
  1042. #endif
  1043.     if (loop_ptr < 0) {
  1044.         in_eval = 0;
  1045.         fatal("Bad label: %s", tmps);
  1046.     }
  1047.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  1048.     }
  1049.     fputs(message,stderr);
  1050.     (void)fflush(stderr);
  1051.     if (e_fp)
  1052.     (void)UNLINK(e_tmpname);
  1053.     statusvalue >>= 8;
  1054.     exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
  1055. }
  1056.  
  1057. /*VARARGS1*/
  1058. void warn(pat,a1,a2,a3,a4)
  1059. char *pat;
  1060. long a1, a2, a3, a4;
  1061. {
  1062.     char *message;
  1063.  
  1064.     message = mess(pat,a1,a2,a3,a4);
  1065.     fputs(message,stderr);
  1066. #ifdef LEAKTEST
  1067. #ifdef DEBUGGING
  1068.     if (debug & 4096)
  1069.     xstat();
  1070. #endif
  1071. #endif
  1072.     (void)fflush(stderr);
  1073. }
  1074. #else
  1075. /*VARARGS0*/
  1076. char *
  1077. mess(args)
  1078. va_list args;
  1079. {
  1080.     char *pat;
  1081.     char *s;
  1082.     STR *tmpstr;
  1083.     int usermess;
  1084. #ifndef HAS_VPRINTF
  1085. #ifdef CHARVSPRINTF
  1086.     char *vsprintf();
  1087. #else
  1088.     int vsprintf();
  1089. #endif
  1090. #endif
  1091.  
  1092. #ifdef lint
  1093.     pat = Nullch;
  1094. #else
  1095.     pat = va_arg(args, char *);
  1096. #endif
  1097.     s = buf;
  1098.     usermess = strEQ(pat, "%s");
  1099.     if (usermess) {
  1100.     tmpstr = str_mortal(&str_undef);
  1101.     str_set(tmpstr, va_arg(args, char *));
  1102.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  1103.     }
  1104.     else {
  1105.     (void) vsprintf(s,pat,args);
  1106.     s += strlen(s);
  1107.     }
  1108.  
  1109.     if (s[-1] != '\n') {
  1110.     if (curcmd->c_line) {
  1111.         (void)sprintf(s," at %s line %ld",
  1112.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  1113.         s += strlen(s);
  1114.     }
  1115.     if (last_in_stab &&
  1116.         stab_io(last_in_stab) &&
  1117.         stab_io(last_in_stab)->lines ) {
  1118.         (void)sprintf(s,", <%s> line %ld",
  1119.           last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
  1120.           (long)stab_io(last_in_stab)->lines);
  1121.         s += strlen(s);
  1122.     }
  1123.     (void)strcpy(s,".\n");
  1124.     if (usermess)
  1125.         str_cat(tmpstr,buf+1);
  1126.     }
  1127.  
  1128.     if (usermess)
  1129.     return tmpstr->str_ptr;
  1130.     else
  1131.     return buf;
  1132. }
  1133.  
  1134. /*VARARGS0*/
  1135. void fatal(va_alist)
  1136. va_dcl
  1137. {
  1138.     va_list args;
  1139.     extern FILE *e_fp;
  1140.     extern char *e_tmpname;
  1141.     char *tmps;
  1142.     char *message;
  1143.  
  1144. #ifndef lint
  1145.     va_start(args);
  1146. #else
  1147.     args = 0;
  1148. #endif
  1149.     message = mess(args);
  1150.     va_end(args);
  1151.     if (in_eval) {
  1152.     str_set(stab_val(stabent("@",TRUE)),message);
  1153.     tmps = "_EVAL_";
  1154.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  1155.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  1156. #ifdef DEBUGGING
  1157.         if (debug & 4) {
  1158.         deb("(Skipping label #%d %s)\n",loop_ptr,
  1159.             loop_stack[loop_ptr].loop_label);
  1160.         }
  1161. #endif
  1162.         loop_ptr--;
  1163.     }
  1164. #ifdef DEBUGGING
  1165.     if (debug & 4) {
  1166.         deb("(Found label #%d %s)\n",loop_ptr,
  1167.         loop_stack[loop_ptr].loop_label);
  1168.     }
  1169. #endif
  1170.     if (loop_ptr < 0) {
  1171.         in_eval = 0;
  1172.         fatal("Bad label: %s", tmps);
  1173.     }
  1174.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  1175.     }
  1176.     fputs(message,stderr);
  1177.     (void)fflush(stderr);
  1178.     if (e_fp)
  1179.     (void)UNLINK(e_tmpname);
  1180.     statusvalue >>= 8;
  1181.     exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
  1182. }
  1183.  
  1184. /*VARARGS0*/
  1185. void warn(va_alist)
  1186. va_dcl
  1187. {
  1188.     va_list args;
  1189.     char *message;
  1190.  
  1191. #ifndef lint
  1192.     va_start(args);
  1193. #else
  1194.     args = 0;
  1195. #endif
  1196.     message = mess(args);
  1197.     va_end(args);
  1198.  
  1199.     fputs(message,stderr);
  1200. #ifdef LEAKTEST
  1201. #ifdef DEBUGGING
  1202.     if (debug & 4096)
  1203.     xstat();
  1204. #endif
  1205. #endif
  1206.     (void)fflush(stderr);
  1207. }
  1208. #endif
  1209.  
  1210. void
  1211. my_setenv(nam,val)
  1212. char *nam, *val;
  1213. {
  1214.     register int i=envix(nam);        /* where does it go? */
  1215.  
  1216.     if (environ == origenviron) {    /* need we copy environment? */
  1217.     int j;
  1218.     int max;
  1219.     char **tmpenv;
  1220.  
  1221.     /*SUPPRESS 530*/
  1222.     for (max = i; environ[max]; max++) ;
  1223.     New(901,tmpenv, max+2, char*);
  1224.     for (j=0; j<max; j++)        /* copy environment */
  1225.         tmpenv[j] = savestr(environ[j]);
  1226.     tmpenv[max] = Nullch;
  1227.     environ = tmpenv;        /* tell exec where it is now */
  1228.     }
  1229.     if (!val) {
  1230.     while (environ[i]) {
  1231.         environ[i] = environ[i+1];
  1232.         i++;
  1233.     }
  1234.     return;
  1235.     }
  1236.     if (!environ[i]) {            /* does not exist yet */
  1237.     Renew(environ, i+2, char*);    /* just expand it a bit */
  1238.     environ[i+1] = Nullch;    /* make sure it's null terminated */
  1239.     }
  1240.     else
  1241.     Safefree(environ[i]);
  1242.     New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
  1243. #ifndef MSDOS
  1244.     (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
  1245. #else
  1246.     /* MS-DOS requires environment variable names to be in uppercase */
  1247.     /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
  1248.      * some utilities and applications may break because they only look
  1249.      * for upper case strings. (Fixed strupr() bug here.)]
  1250.      */
  1251.     strcpy(environ[i],nam); strupr(environ[i]);
  1252.     (void)sprintf(environ[i] + strlen(nam),"=%s",val);
  1253. #endif /* MSDOS */
  1254. }
  1255.  
  1256. int
  1257. envix(nam)
  1258. char *nam;
  1259. {
  1260.     register int i, len = strlen(nam);
  1261.  
  1262.     for (i = 0; environ[i]; i++) {
  1263.     if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
  1264.         break;            /* strnEQ must come first to avoid */
  1265.     }                    /* potential SEGV's */
  1266.     return i;
  1267. }
  1268.  
  1269. #ifdef EUNICE
  1270. int
  1271. unlnk(f)    /* unlink all versions of a file */
  1272. char *f;
  1273. {
  1274.     int i;
  1275.  
  1276.     for (i = 0; unlink(f) >= 0; i++) ;
  1277.     return i ? 0 : -1;
  1278. }
  1279. #endif
  1280.  
  1281. #if !defined(HAS_BCOPY) || !defined(SAFE_BCOPY)
  1282. char *
  1283. my_bcopy(from,to,len)
  1284. register char *from;
  1285. register char *to;
  1286. register int len;
  1287. {
  1288.     char *retval = to;
  1289.  
  1290.     if (from - to >= 0) {
  1291.     while (len--)
  1292.         *to++ = *from++;
  1293.     }
  1294.     else {
  1295.     to += len;
  1296.     from += len;
  1297.     while (len--)
  1298.         *(--to) = *(--from);
  1299.     }
  1300.     return retval;
  1301. }
  1302. #endif
  1303.  
  1304. #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
  1305. char *
  1306. my_bzero(loc,len)
  1307. register char *loc;
  1308. register int len;
  1309. {
  1310.     char *retval = loc;
  1311.  
  1312.     while (len--)
  1313.     *loc++ = 0;
  1314.     return retval;
  1315. }
  1316. #endif
  1317.  
  1318. #ifndef HAS_MEMCMP
  1319. int
  1320. my_memcmp(s1,s2,len)
  1321. register unsigned char *s1;
  1322. register unsigned char *s2;
  1323. register int len;
  1324. {
  1325.     register int tmp;
  1326.  
  1327.     while (len--) {
  1328.     if (tmp = *s1++ - *s2++)
  1329.         return tmp;
  1330.     }
  1331.     return 0;
  1332. }
  1333. #endif /* HAS_MEMCMP */
  1334.  
  1335. #ifdef I_VARARGS
  1336. #ifndef HAS_VPRINTF
  1337.  
  1338. #ifdef CHARVSPRINTF
  1339. char *
  1340. #else
  1341. int
  1342. #endif
  1343. vsprintf(dest, pat, args)
  1344. char *dest, *pat, *args;
  1345. {
  1346.     FILE fakebuf;
  1347.  
  1348.     fakebuf._ptr = dest;
  1349.     fakebuf._cnt = 32767;
  1350. #ifndef _IOSTRG
  1351. #define _IOSTRG 0
  1352. #endif
  1353.     fakebuf._flag = _IOWRT|_IOSTRG;
  1354.     _doprnt(pat, args, &fakebuf);    /* what a kludge */
  1355.     (void)putc('\0', &fakebuf);
  1356. #ifdef CHARVSPRINTF
  1357.     return(dest);
  1358. #else
  1359.     return 0;        /* perl doesn't use return value */
  1360. #endif
  1361. }
  1362.  
  1363. #ifdef DEBUGGING
  1364. int
  1365. vfprintf(fd, pat, args)
  1366. FILE *fd;
  1367. char *pat, *args;
  1368. {
  1369.     _doprnt(pat, args, fd);
  1370.     return 0;        /* wrong, but perl doesn't use the return value */
  1371. }
  1372. #endif
  1373. #endif /* HAS_VPRINTF */
  1374. #endif /* I_VARARGS */
  1375.  
  1376. /*
  1377.  * I think my_swap(), htonl() and ntohl() have never been used.
  1378.  * perl.h contains last-chance references to my_swap(), my_htonl()
  1379.  * and my_ntohl().  I presume these are the intended functions;
  1380.  * but htonl() and ntohl() have the wrong names.  There are no
  1381.  * functions my_htonl() and my_ntohl() defined anywhere.
  1382.  * -DWS
  1383.  */
  1384. #ifdef MYSWAP
  1385. #if BYTEORDER != 0x4321
  1386. short
  1387. my_swap(s)
  1388. short s;
  1389. {
  1390. #if (BYTEORDER & 1) == 0
  1391.     short result;
  1392.  
  1393.     result = ((s & 255) << 8) + ((s >> 8) & 255);
  1394.     return result;
  1395. #else
  1396.     return s;
  1397. #endif
  1398. }
  1399.  
  1400. long
  1401. htonl(l)
  1402. register long l;
  1403. {
  1404.     union {
  1405.     long result;
  1406.     char c[sizeof(long)];
  1407.     } u;
  1408.  
  1409. #if BYTEORDER == 0x1234
  1410.     u.c[0] = (l >> 24) & 255;
  1411.     u.c[1] = (l >> 16) & 255;
  1412.     u.c[2] = (l >> 8) & 255;
  1413.     u.c[3] = l & 255;
  1414.     return u.result;
  1415. #else
  1416. #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
  1417.     fatal("Unknown BYTEORDER\n");
  1418. #else
  1419.     register int o;
  1420.     register int s;
  1421.  
  1422.     for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
  1423.     u.c[o & 0xf] = (l >> s) & 255;
  1424.     }
  1425.     return u.result;
  1426. #endif
  1427. #endif
  1428. }
  1429.  
  1430. long
  1431. ntohl(l)
  1432. register long l;
  1433. {
  1434.     union {
  1435.     long l;
  1436.     char c[sizeof(long)];
  1437.     } u;
  1438.  
  1439. #if BYTEORDER == 0x1234
  1440.     u.c[0] = (l >> 24) & 255;
  1441.     u.c[1] = (l >> 16) & 255;
  1442.     u.c[2] = (l >> 8) & 255;
  1443.     u.c[3] = l & 255;
  1444.     return u.l;
  1445. #else
  1446. #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
  1447.     fatal("Unknown BYTEORDER\n");
  1448. #else
  1449.     register int o;
  1450.     register int s;
  1451.  
  1452.     u.l = l;
  1453.     l = 0;
  1454.     for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
  1455.     l |= (u.c[o & 0xf] & 255) << s;
  1456.     }
  1457.     return l;
  1458. #endif
  1459. #endif
  1460. }
  1461.  
  1462. #endif /* BYTEORDER != 0x4321 */
  1463. #endif /* MYSWAP */
  1464.  
  1465. /*
  1466.  * Little-endian byte order functions - 'v' for 'VAX', or 'reVerse'.
  1467.  * If these functions are defined,
  1468.  * the BYTEORDER is neither 0x1234 nor 0x4321.
  1469.  * However, this is not assumed.
  1470.  * -DWS
  1471.  */
  1472.  
  1473. #define HTOV(name,type)                        \
  1474.     type                            \
  1475.     name (n)                        \
  1476.     register type n;                    \
  1477.     {                            \
  1478.         union {                        \
  1479.         type value;                    \
  1480.         char c[sizeof(type)];                \
  1481.         } u;                        \
  1482.         register int i;                    \
  1483.         register int s;                    \
  1484.         for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) {    \
  1485.         u.c[i] = (n >> s) & 0xFF;            \
  1486.         }                            \
  1487.         return u.value;                    \
  1488.     }
  1489.  
  1490. #define VTOH(name,type)                        \
  1491.     type                            \
  1492.     name (n)                        \
  1493.     register type n;                    \
  1494.     {                            \
  1495.         union {                        \
  1496.         type value;                    \
  1497.         char c[sizeof(type)];                \
  1498.         } u;                        \
  1499.         register int i;                    \
  1500.         register int s;                    \
  1501.         u.value = n;                    \
  1502.         n = 0;                        \
  1503.         for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) {    \
  1504.         n += (u.c[i] & 0xFF) << s;            \
  1505.         }                            \
  1506.         return n;                        \
  1507.     }
  1508.  
  1509. #if defined(HAS_HTOVS) && !defined(htovs)
  1510. HTOV(htovs,short)
  1511. #endif
  1512. #if defined(HAS_HTOVL) && !defined(htovl)
  1513. HTOV(htovl,long)
  1514. #endif
  1515. #if defined(HAS_VTOHS) && !defined(vtohs)
  1516. VTOH(vtohs,short)
  1517. #endif
  1518. #if defined(HAS_VTOHL) && !defined(vtohl)
  1519. VTOH(vtohl,long)
  1520. #endif
  1521.  
  1522. #ifndef MSMAC
  1523. FILE *
  1524. mypopen(cmd,mode)
  1525. char    *cmd;
  1526. char    *mode;
  1527. {
  1528.     int p[2];
  1529.     register int this, that;
  1530.     register int pid;
  1531.     STR *str;
  1532.     int doexec = strNE(cmd,"-");
  1533.  
  1534.     if (pipe(p) < 0)
  1535.     return Nullfp;
  1536.     this = (*mode == 'w');
  1537.     that = !this;
  1538. #ifdef TAINT
  1539.     if (doexec) {
  1540.     taintenv();
  1541.     taintproper("Insecure dependency in exec");
  1542.     }
  1543. #endif
  1544.     while ((pid = (doexec?vfork():fork())) < 0) {
  1545.     if (errno != EAGAIN) {
  1546.         close(p[this]);
  1547.         if (!doexec)
  1548.         fatal("Can't fork");
  1549.         return Nullfp;
  1550.     }
  1551.     sleep(5);
  1552.     }
  1553.     if (pid == 0) {
  1554. #define THIS that
  1555. #define THAT this
  1556.     close(p[THAT]);
  1557.     if (p[THIS] != (*mode == 'r')) {
  1558.         dup2(p[THIS], *mode == 'r');
  1559.         close(p[THIS]);
  1560.     }
  1561.     if (doexec) {
  1562. #if !defined(HAS_FCNTL) || !defined(F_SETFD)
  1563.         int fd;
  1564.  
  1565. #ifndef NOFILE
  1566. #define NOFILE 20
  1567. #endif
  1568.         for (fd = maxsysfd + 1; fd < NOFILE; fd++)
  1569.         close(fd);
  1570. #endif
  1571.         do_exec(cmd);    /* may or may not use the shell */
  1572.         warn("Can't exec \"%s\": %s", cmd, strerror(errno));
  1573.         _exit(1);
  1574.     }
  1575.     /*SUPPRESS 560*/
  1576.     if (tmpstab = stabent("$",allstabs))
  1577.         str_numset(STAB_STR(tmpstab),(double)getpid());
  1578.     forkprocess = 0;
  1579.     hclear(pidstatus, FALSE);    /* we have no children */
  1580.     return Nullfp;
  1581. #undef THIS
  1582. #undef THAT
  1583.     }
  1584.     do_execfree();    /* free any memory malloced by child on vfork */
  1585.     close(p[that]);
  1586.     if (p[that] < p[this]) {
  1587.     dup2(p[this], p[that]);
  1588.     close(p[this]);
  1589.     p[this] = p[that];
  1590.     }
  1591.     str = afetch(fdpid,p[this],TRUE);
  1592.     str->str_u.str_useful = pid;
  1593.     forkprocess = pid;
  1594.     return fdopen(p[this], mode);
  1595. }
  1596. #endif /* !MSMAC */
  1597.  
  1598. #ifdef NOTDEF
  1599. dumpfds(s)
  1600. char *s;
  1601. {
  1602.     int fd;
  1603.     struct stat tmpstatbuf;
  1604.  
  1605.     fprintf(stderr,"%s", s);
  1606.     for (fd = 0; fd < 32; fd++) {
  1607.     if (fstat(fd,&tmpstatbuf) >= 0)
  1608.         fprintf(stderr," %d",fd);
  1609.     }
  1610.     fprintf(stderr,"\n");
  1611. }
  1612. #endif
  1613.  
  1614. #ifndef HAS_DUP2
  1615. dup2(oldfd,newfd)
  1616. int oldfd;
  1617. int newfd;
  1618. {
  1619. #if defined(HAS_FCNTL) && defined(F_DUPFD)
  1620.     close(newfd);
  1621.     fcntl(oldfd, F_DUPFD, newfd);
  1622. #else
  1623.     int fdtmp[256];
  1624.     int fdx = 0;
  1625.     int fd;
  1626.  
  1627.     if (oldfd == newfd)
  1628.     return 0;
  1629.     close(newfd);
  1630.     while ((fd = dup(oldfd)) != newfd)    /* good enough for low fd's */
  1631.     fdtmp[fdx++] = fd;
  1632.     while (fdx > 0)
  1633.     close(fdtmp[--fdx]);
  1634. #endif
  1635. }
  1636. #endif
  1637.  
  1638. #ifndef MSMAC
  1639. int
  1640. mypclose(ptr)
  1641. FILE *ptr;
  1642. {
  1643. #ifdef VOIDSIG
  1644.     void (*hstat)(), (*istat)(), (*qstat)();
  1645. #else
  1646.     int (*hstat)(), (*istat)(), (*qstat)();
  1647. #endif
  1648.     int status;
  1649.     STR *str;
  1650.     int pid;
  1651.  
  1652.     str = afetch(fdpid,fileno(ptr),TRUE);
  1653.     pid = (int)str->str_u.str_useful;
  1654.     astore(fdpid,fileno(ptr),Nullstr);
  1655.     fclose(ptr);
  1656. #ifdef UTS
  1657.     if(kill(pid, 0) < 0) { return(pid); }   /* HOM 12/23/91 */
  1658. #endif
  1659.     hstat = signal(SIGHUP, SIG_IGN);
  1660.     istat = signal(SIGINT, SIG_IGN);
  1661.     qstat = signal(SIGQUIT, SIG_IGN);
  1662.     pid = wait4pid(pid, &status, 0);
  1663.     signal(SIGHUP, hstat);
  1664.     signal(SIGINT, istat);
  1665.     signal(SIGQUIT, qstat);
  1666.     return(pid < 0 ? pid : status);
  1667. }
  1668.  
  1669. int
  1670. wait4pid(pid,statusp,flags)
  1671. int pid;
  1672. int *statusp;
  1673. int flags;
  1674. {
  1675. #if !defined(HAS_WAIT4) && !defined(HAS_WAITPID)
  1676.     int result;
  1677.     STR *str;
  1678.     char spid[16];
  1679. #endif
  1680.  
  1681.     if (!pid)
  1682.     return -1;
  1683. #ifdef HAS_WAIT4
  1684.     return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
  1685. #else
  1686. #ifdef HAS_WAITPID
  1687.     return waitpid(pid,statusp,flags);
  1688. #else
  1689.     if (pid > 0) {
  1690.     sprintf(spid, "%d", pid);
  1691.     str = hfetch(pidstatus,spid,strlen(spid),FALSE);
  1692.     if (str != &str_undef) {
  1693.         *statusp = (int)str->str_u.str_useful;
  1694.         hdelete(pidstatus,spid,strlen(spid));
  1695.         return pid;
  1696.     }
  1697.     }
  1698.     else {
  1699.     HENT *entry;
  1700.  
  1701.     hiterinit(pidstatus);
  1702.     if (entry = hiternext(pidstatus)) {
  1703.         pid = atoi(hiterkey(entry,statusp));
  1704.         str = hiterval(pidstatus,entry);
  1705.         *statusp = (int)str->str_u.str_useful;
  1706.         sprintf(spid, "%d", pid);
  1707.         hdelete(pidstatus,spid,strlen(spid));
  1708.         return pid;
  1709.     }
  1710.     }
  1711.     if (flags)
  1712.     fatal("Can't do waitpid with flags");
  1713.     else {
  1714.     while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
  1715.         pidgone(result,*statusp);
  1716.     if (result < 0)
  1717.         *statusp = -1;
  1718.     }
  1719.     return result;
  1720. #endif
  1721. #endif
  1722. }
  1723. #endif /* !MSMAC */
  1724.  
  1725. void
  1726. /*SUPPRESS 590*/
  1727. pidgone(pid,status)
  1728. int pid;
  1729. int status;
  1730. {
  1731. #if defined(HAS_WAIT4) || defined(HAS_WAITPID)
  1732. #else
  1733.     register STR *str;
  1734.     char spid[16];
  1735.  
  1736.     sprintf(spid, "%d", pid);
  1737.     str = hfetch(pidstatus,spid,strlen(spid),TRUE);
  1738.     str->str_u.str_useful = status;
  1739. #endif
  1740.     return;
  1741. }
  1742.  
  1743. #ifndef HAS_MEMCMP
  1744. memcmp(s1,s2,len)
  1745. register unsigned char *s1;
  1746. register unsigned char *s2;
  1747. register int len;
  1748. {
  1749.     register int tmp;
  1750.  
  1751.     while (len--) {
  1752.     if (tmp = *s1++ - *s2++)
  1753.         return tmp;
  1754.     }
  1755.     return 0;
  1756. }
  1757. #endif /* HAS_MEMCMP */
  1758.  
  1759. void
  1760. repeatcpy(to,from,len,count)
  1761. register char *to;
  1762. register char *from;
  1763. int len;
  1764. register int count;
  1765. {
  1766.     register int todo;
  1767.     register char *frombase = from;
  1768.  
  1769.     if (len == 1) {
  1770.     todo = *from;
  1771.     while (count-- > 0)
  1772.         *to++ = todo;
  1773.     return;
  1774.     }
  1775.     while (count-- > 0) {
  1776.     for (todo = len; todo > 0; todo--) {
  1777.         *to++ = *from++;
  1778.     }
  1779.     from = frombase;
  1780.     }
  1781. }
  1782.  
  1783. #ifndef CASTNEGFLOAT
  1784. unsigned long
  1785. castulong(f)
  1786. double f;
  1787. {
  1788.     long along;
  1789.  
  1790. #if CASTFLAGS & 2
  1791. #   define BIGDOUBLE 2147483648.0
  1792.     if (f >= BIGDOUBLE)
  1793.     return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
  1794. #endif
  1795.     if (f >= 0.0)
  1796.     return (unsigned long)f;
  1797.     along = (long)f;
  1798.     return (unsigned long)along;
  1799. }
  1800. #endif
  1801.  
  1802. #ifndef HAS_RENAME
  1803. int
  1804. same_dirent(a,b)
  1805. char *a;
  1806. char *b;
  1807. {
  1808.     char *fa = rindex(a,'/');
  1809.     char *fb = rindex(b,'/');
  1810.     struct stat tmpstatbuf1;
  1811.     struct stat tmpstatbuf2;
  1812. #ifndef MAXPATHLEN
  1813. #define MAXPATHLEN 1024
  1814. #endif
  1815.     char tmpbuf[MAXPATHLEN+1];
  1816.  
  1817.     if (fa)
  1818.     fa++;
  1819.     else
  1820.     fa = a;
  1821.     if (fb)
  1822.     fb++;
  1823.     else
  1824.     fb = b;
  1825.     if (strNE(a,b))
  1826.     return FALSE;
  1827.     if (fa == a)
  1828.     strcpy(tmpbuf,".");
  1829.     else
  1830.     strncpy(tmpbuf, a, fa - a);
  1831.     if (stat(tmpbuf, &tmpstatbuf1) < 0)
  1832.     return FALSE;
  1833.     if (fb == b)
  1834.     strcpy(tmpbuf,".");
  1835.     else
  1836.     strncpy(tmpbuf, b, fb - b);
  1837.     if (stat(tmpbuf, &tmpstatbuf2) < 0)
  1838.     return FALSE;
  1839.     return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
  1840.        tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
  1841. }
  1842. #endif /* !HAS_RENAME */
  1843.  
  1844. unsigned long
  1845. scanoct(start, len, retlen)
  1846. char *start;
  1847. int len;
  1848. int *retlen;
  1849. {
  1850.     register char *s = start;
  1851.     register unsigned long retval = 0;
  1852.  
  1853.     while (len-- && *s >= '0' && *s <= '7') {
  1854.     retval <<= 3;
  1855.     retval |= *s++ - '0';
  1856.     }
  1857.     *retlen = s - start;
  1858.     return retval;
  1859. }
  1860.  
  1861. unsigned long
  1862. scanhex(start, len, retlen)
  1863. char *start;
  1864. int len;
  1865. int *retlen;
  1866. {
  1867.     register char *s = start;
  1868.     register unsigned long retval = 0;
  1869.     char *tmp;
  1870.  
  1871.     while (len-- && *s && (tmp = index(hexdigit, *s))) {
  1872.     retval <<= 4;
  1873.     retval |= (tmp - hexdigit) & 15;
  1874.     s++;
  1875.     }
  1876.     *retlen = s - start;
  1877.     return retval;
  1878. }
  1879.  
  1880. #ifdef macintosh
  1881. void reinit_util()
  1882. {
  1883. #ifndef safemalloc
  1884. #ifdef DEBUGGING
  1885.     an = 0;
  1886. #endif
  1887. #endif
  1888. }
  1889. #endif